package com.anjiplus.template.gaea.gateway.filter;

import com.anjiplus.template.gaea.gateway.utils.GaeaWebFluxUtils;
import com.anji.plus.gaea.GaeaProperties;
import com.anji.plus.gaea.cache.CacheHelper;
import com.anji.plus.gaea.constant.Enabled;
import com.anji.plus.gaea.constant.GaeaConstant;
import com.anji.plus.gaea.constant.GaeaKeyConstant;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.*;

import static com.anji.plus.gaea.constant.GaeaConstant.URL_REPLACEMENT;
import static com.anji.plus.gaea.constant.GaeaKeyConstant.USER_ROLE_SET_PREFIX;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;

/**
 * 校验当前用户是否有权限,如果当前URL没有配置，则不校验
 * 这是种消极的校验：不配置就不校验，只校验配置的
 * @author lr
 * @since 2021-03-01
 */
public class GlobalSecurityAccessFilter implements GlobalFilter, Ordered {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Autowired
    private CacheHelper cacheHelper;

    @Autowired
    private GaeaProperties gaeaProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //判断是否设置跳过标识
        Enabled attributeOrDefault = exchange.getAttributeOrDefault(SkipAuthenticationGatewayFilterFactory.SKIP, Enabled.NO);
        if (attributeOrDefault == Enabled.YES) {
            return chain.filter(exchange);
        }

        //判断是否有跳过标识
        Integer skip = exchange.getAttribute(GaeaWebFluxUtils.SKIP);

        String username = exchange.getAttribute(GaeaWebFluxUtils.USER_NAME);

        //超级用户不需要鉴权
        if (skip != null || StringUtils.equals(GaeaConstant.SUPER_USER_NAME, username)) {
            return chain.filter(exchange);
        }

        ServerHttpRequest request = exchange.getRequest();

        //从请求头中获取组织编码
        String orgCode = request.getHeaders().getFirst("orgCode");

        //请求方法
        String methodValue = request.getMethodValue();

        //请求路径(最终的请求路径)
        URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);

        //请求方法+#+请求路径
        String urlKey = methodValue + GaeaConstant.URL_SPLIT + requestUrl.getPath();

        Map<String, String> urlRoleMap = cacheHelper.hashGet(GaeaKeyConstant.HASH_URL_ROLE_KEY + orgCode);

        String roles = "";

        // 查询当前属于哪个服务
//        Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
//        String applicationName = route.getId();
        Map<String, String> applicationNameAllAuthorities = cacheHelper.hashGet(GaeaKeyConstant.AUTHORITY_ALL_MAP_PREFIX);

        //查询当前请求是否在对应的权限里。即：先精确匹配(保证当前路由是需要精确匹配还是模糊匹配，防止精确匹配的被模糊匹配）
        // 比如：/user/info和/user/**同时存在，/user/info,被/user/**匹配掉
        if (applicationNameAllAuthorities.containsKey(urlKey)) {
            roles = urlRoleMap.get(urlKey);
        } else {
            Optional<String> optional = urlRoleMap.keySet().stream()
                    .filter(key -> StringUtils.isNotBlank(key) && key.contains(URL_REPLACEMENT))
                    .filter(key -> antPathMatcher.match(key, urlKey)).findFirst();
            if (optional.isPresent()) {
                roles = urlRoleMap.get(optional.get());
            }
        }

        //当不包含角色的时候就放过
        if (StringUtils.isBlank(roles)) {
            if (gaeaProperties.getSecurity().isPermitAll()) {
                return chain.filter(exchange);
            } else {
                return GaeaWebFluxUtils.getFilterResult(exchange, "User.no.authority","没有权限");
            }
        }
        //路径需要的角色列表
        String[] roleArray = roles.split(GaeaConstant.SPLIT);

        Map<String, String> userOrgRoleMap = cacheHelper.hashGet(USER_ROLE_SET_PREFIX + username);
        if (CollectionUtils.isEmpty(userOrgRoleMap) || !userOrgRoleMap.containsKey(orgCode) || StringUtils.isBlank(userOrgRoleMap.get(orgCode))) {
            return GaeaWebFluxUtils.getFilterResult(exchange, "User.no.authority","没有权限");
        }

        //用户拥有的角色
        String[] userHasRoles = userOrgRoleMap.get(orgCode).split(GaeaConstant.SPLIT);

        List<String> roleNeeds = new ArrayList<>();
        roleNeeds.addAll(Arrays.asList(roleArray));

        List<String> userHasRoleList = new ArrayList<>();
        userHasRoleList.addAll(Arrays.asList(userHasRoles));
        //取交集
        roleNeeds.retainAll(userHasRoleList);
        if (CollectionUtils.isEmpty(roleNeeds)) {
            return GaeaWebFluxUtils.getFilterResult(exchange, "User.no.authority", "没有权限");
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 1;
    }


    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("admin");
        List<String> list1 = new ArrayList<>();
        list1.add("admin");

        boolean b = list.retainAll(list1);
        System.out.println(b);


    }
}
